import logging
import os
import threading
import time
import uuid

from PIL import Image

from blls.base_bll import BaseBLL
from config import REMOTE, API_SECRET
from dtos.result import Result
from models.data_models.data_model import Data
from models.project_models.project_model import Project
from utils.common_util import CommonUtil
from libs.redis_wrapper import RedisWrapper
from datetime import datetime
class ImgBLL(BaseBLL):

    # @staticmethod
    # def set_zip_file(user_id, task_id, zip_file, ttl=None):
    #     """设置用户的压缩文件路径，并可选设置过期时间"""
    #     key = f'zip_file:{user_id}:{task_id}'
    #     RedisWrapper.set(key, zip_file, ex=ttl)
    #
    # @staticmethod
    # def get_zip_file(user_id, task_id):
    #     """获取用户的压缩文件路径"""
    #     key = f'zip_file:{user_id}:{task_id}'
    #     value = RedisWrapper.get(key)
    #     return value.decode('utf-8') if value else None
    #
    # @staticmethod
    # def set_task_id(user_id, task_id, ttl=None):
    #     """设置用户的任务 ID，并可选设置过期时间"""
    #     key = f'task_id:{user_id}'
    #     RedisWrapper.set(key, task_id, ex=ttl)
    #
    # @staticmethod
    # def get_task_id(user_id):
    #     """获取用户的任务 ID"""
    #     key = f'task_id:{user_id}'
    #     value = RedisWrapper.get(key)
    #     return value.decode('utf-8') if value else None
    #
    # def download_img(self, data):
    #     if not data["date"]:
    #         return Result.error_result(message="请输入日期")
    #
    #     data_obj = datetime.strptime(data['date'], '%Y-%m-%d')
    #     year = data_obj.year
    #     month = data_obj.month
    #     day = data_obj.day
    #     remote_dir = f"{REMOTE}{year}/{month}/{day}"
    #     local_zip_file = os.path.join(REMOTE,'images', f"{year}-{month}-{day}_{uuid.uuid4()}.zip")
    #
    #     if not os.path.exists(REMOTE + 'images'):
    #         os.makedirs(REMOTE + 'images')
    #
    #     # 生成唯一任务标识符
    #     task_id = str(uuid.uuid4())
    #
    #     # 将 task_id 存储到 Redis 中，并设置过期时间（例如，24小时后过期）
    #     user_id = self.get_current_user_id()
    #     ImgBLL.set_task_id(user_id, task_id, ttl=86400)
    #
    #     # 将 zip_file 路径存储到 Redis 中，并设置过期时间（例如，24小时后过期）
    #     ImgBLL.set_zip_file(user_id, task_id, local_zip_file, ttl=86400)
    #     # 启动后台线程进行压缩
    #     thread = threading.Thread(target=CommonUtil.zip_dir, args=(user_id, task_id, remote_dir, local_zip_file))
    #     thread.start()
    #     #等待一段时间，让线程有机会运行
    #     return Result.success_result(
    #         data=self.get_file_http_url(local_zip_file),
    #         message="图片正在压缩"
    #     )
    #
    # def download_progress(self):
    #     user_id = self.get_current_user_id()
    #     task_id = ImgBLL.get_task_id(user_id)  # 从 Redis 中获取当前任务的 task_id
    #     if not task_id:
    #         return Result.error_result(message="未找到任务 ID")
    #
    #     zip_file = ImgBLL.get_zip_file(user_id, task_id)
    #     if not zip_file:
    #         return Result.error_result(message="未找到压缩文件路径")
    #
    #     progress = CommonUtil.get_progress(user_id, task_id, zip_file)
    #     return Result.success_result(data={"progress": progress})

    @staticmethod
    def set_zip_file(user_id, task_id, zip_file, ttl=None):
        """设置用户的压缩文件路径，并可选设置过期时间"""
        key = f'zip_file:{user_id}:{task_id}'
        RedisWrapper.set(key, zip_file, ex=ttl)

    @staticmethod
    def get_zip_file(user_id, task_id):
        """获取用户的压缩文件路径"""
        key = f'zip_file:{user_id}:{task_id}'
        value = RedisWrapper.get(key)
        return value.decode('utf-8') if value else None

    @staticmethod
    def set_task_id(user_id, task_id, ttl=None):
        """设置用户的任务 ID，并可选设置过期时间"""
        key = f'task_id:{user_id}'
        RedisWrapper.set(key, task_id, ex=ttl)

    @staticmethod
    def get_task_id(user_id):
        """获取用户的任务 ID"""
        key = f'task_id:{user_id}'
        value = RedisWrapper.get(key)
        return value.decode('utf-8') if value else None

    def download_img(self, data):
        if not data["date"]:
            return Result.error_result(message="请输入日期")

        data_obj = datetime.strptime(data['date'], '%Y-%m-%d')
        year = data_obj.year
        month = data_obj.month
        day = data_obj.day
        remote_dir = f"{REMOTE}{year}/{month}/{day}"
        local_zip_file = os.path.join(REMOTE, 'images', f"{year}-{month}-{day}_{uuid.uuid4()}.zip")

        if not os.path.exists(os.path.join(REMOTE, 'images')):
            os.makedirs(os.path.join(REMOTE, 'images'))

        # 生成唯一任务标识符
        task_id = str(uuid.uuid4())

        # 将 task_id 存储到 Redis 中，并设置过期时间（例如，24小时后过期）
        user_id = self.get_current_user_id()
        ImgBLL.set_task_id(user_id, task_id, ttl=86400)

        # 将 zip_file 路径存储到 Redis 中，并设置过期时间（例如，24小时后过期）
        ImgBLL.set_zip_file(user_id, task_id, local_zip_file, ttl=86400)
        # 启动后台线程进行压缩
        thread = threading.Thread(target=CommonUtil.zip_dir, args=(user_id, task_id, remote_dir, local_zip_file))
        thread.start()
        return Result.success_result(
            data=self.get_file_http_url(local_zip_file),
            message="图片正在压缩"
        )

    def download_progress(self):
        user_id = self.get_current_user_id()
        task_id = ImgBLL.get_task_id(user_id)  # 从 Redis 中获取当前任务的 task_id
        if not task_id:
            return Result.error_result(message="未找到任务 ID")

        zip_file = ImgBLL.get_zip_file(user_id, task_id)
        if not zip_file:
            return Result.error_result(message="未找到压缩文件路径")

        progress = CommonUtil.get_progress(user_id, task_id, zip_file)
        return Result.success_result(data={"progress": progress})


    def updata_result(self, **res_data):
        user_id = self.get_current_user_id()
        project_id = res_data['project_id']
        key_2 = f"project_update:{project_id}:{user_id}"
        value = RedisWrapper.get(key_2)
        if value:
            return Result.success_result(message="更新完成")
        else:
            return Result.error_result(message="")

    def upload_img(self, files, res_data):
        UPLOAD_FOLDER = '/nfs/imgs/label/data/koutu-1'
        if 'origin' not in files.keys():
            return Result.error_result(message="请上传原图")
        if 'retouch' not in files.keys():
            return Result.error_result(message="请上传修图")
        origin = files['origin']
        retouch = files['retouch']
        origin_name = origin[0]['filename']
        origin_body = origin[0]['body']
        retouch_name = retouch[0]['filename']
        retouch_body = retouch[0]['body']
        # if origin_name.split('.')[0] != retouch_name.split('.')[0]:
        #     return Result.error_result(message="原图与修图名称不一致")
        timestamp = int(res_data.pop("timestamp"))
        stype = ['.jpg', '.jpeg', '.png']
        if not (origin_name.lower().endswith(tuple(stype)) and retouch_name.lower().endswith(tuple(stype))):
            return Result.error_result(message="请上传jpg(jpeg)或png格式图片")
        sign = res_data.pop("sign")
        if timestamp < int(time.time()) - 300:
            return Result.error_result(message="请求超时")
        if not (sign == CommonUtil.get_sign(origin, retouch, timestamp, API_SECRET)):
            return Result.error_result(message="校验未通过")
        try:
            # 确保上传目录存在
            if not os.path.exists(UPLOAD_FOLDER):
                os.makedirs(UPLOAD_FOLDER)
            # 生成随机后缀
            random_suffix = str(uuid.uuid4())

            # 添加随机后缀到文件名
            origin_name_parts = origin_name.rsplit('.', 1)
            retouch_name_parts = retouch_name.rsplit('.', 1)
            new_origin_name = f"{origin_name_parts[0]}_{random_suffix}.{origin_name_parts[1]}"
            new_retouch_name = f"{retouch_name_parts[0]}_{random_suffix}.{retouch_name_parts[1]}"

            # 保存原图
            origin_path = os.path.join(UPLOAD_FOLDER, new_origin_name)
            with open(origin_path, 'wb') as f:
                f.write(origin_body)
            print(f"原图 {new_origin_name} 上传成功，保存路径为 {origin_path}")

            # 保存修图
            retouch_path = os.path.join(UPLOAD_FOLDER, new_retouch_name)
            with open(retouch_path, 'wb') as f:
                f.write(retouch_body)

            im = Image.open(origin_path)
            width, height = im.size
            size = ",".join(map(str, (1,) + (height, width)))
            self.db_session.begin(subtransactions=True)
            project_obj = self.db_session.query(Project).filter(Project.project_id == 12).first()
            project_obj.state = 1
            info = {
                "project_id": 12,
                "path": new_origin_name,
                "path_2": new_retouch_name,
                "size": size,
                "is_delete": 0,
                "conform": 1
            }
            data_info = Data(**info)
            self.db_session.add(data_info)
            self.db_session.commit()
            print(f"修图 {new_retouch_name} 上传成功，保存路径为 {retouch_path}")

            return Result.success_result(message="上传成功")

        except Exception as e:
            logging.info(f"文件保存失败: {e}")
            return Result.error_result(message="文件保存失败")

    def data_result(self, data):
        info = [{
            "date": "2023-03-31",
            "name": "test1",
            "importance": "1",
            "detail": "[reasoning]### 思考过程\n- <font size=2>正在检查任务时效性</font>\n- <font size=2>时效性结果: 需及时回复</font>\n- <font size=2>正在给问题进行系统分类</font>\n- <font size=2>系统分类结果: 其他</font>\n[/reasoning]\n[inference]### Python实现冒泡排序\n\n```python\ndef bubble_sort(arr):\n    n = len(arr)\n    for i in range(n):\n        for j in range(0, n-i-1):\n            if arr[j] > arr[j+1]:\n                arr[j], arr[j+1] = arr[j+1], arr[j]\n    return arr\n```\n\n### 步骤\n1. **遍历数组**：从第一个元素到最后一个元素。\n2. **比较相邻元素**：如果前一个元素大于后一个元素，交换它们。\n3. **重复步骤**：直到没有元素需要交换。[/inference]"
        },{
            "date": "2023-03-31",
            "name": "test2",
            "importance": "2",
            "detail": ""
        }]
        return Result.success_result(message="更新完成",data=info)